package strategies

import (
	"context"
	"fmt"
	"math"

	"github.com/gogf/gf/v2/os/gtime"

	"goldtree/internal/strategy"
)

// RSIStrategy RSI相对强弱指标策略
type RSIStrategy struct {
	*strategy.BaseStrategy
	period      int                    // RSI计算周期
	overbought  float64               // 超买阈值
	oversold    float64               // 超卖阈值
	priceData   map[string][]float64  // 价格数据缓存
	rsiData     map[string][]float64  // RSI数据缓存
	lastSignals map[string]strategy.SignalType // 最后信号
}

// NewRSIStrategy 创建RSI策略
func NewRSIStrategy() strategy.Strategy {
	return &RSIStrategy{
		BaseStrategy: strategy.NewBaseStrategy(),
		priceData:    make(map[string][]float64),
		rsiData:      make(map[string][]float64),
		lastSignals:  make(map[string]strategy.SignalType),
	}
}

// GetInfo 获取策略信息
func (s *RSIStrategy) GetInfo() *strategy.StrategyInfo {
	return &strategy.StrategyInfo{
		Name:        "RSI相对强弱指标策略",
		Version:     "1.0.0",
		Description: "基于RSI指标的超买超卖策略",
		Author:      "GoldTree",
		Parameters: []*strategy.ParameterDef{
			{
				Name:         "period",
				Type:         "int",
				DefaultValue: 14,
				MinValue:     2,
				MaxValue:     50,
				Description:  "RSI计算周期",
				Required:     true,
			},
			{
				Name:         "overbought",
				Type:         "float",
				DefaultValue: 70.0,
				MinValue:     50.0,
				MaxValue:     90.0,
				Description:  "超买阈值",
				Required:     true,
			},
			{
				Name:         "oversold",
				Type:         "float",
				DefaultValue: 30.0,
				MinValue:     10.0,
				MaxValue:     50.0,
				Description:  "超卖阈值",
				Required:     true,
			},
		},
		RequiredData: []string{"kline", "price"},
	}
}

// Initialize 初始化策略
func (s *RSIStrategy) Initialize(ctx context.Context, config *strategy.StrategyConfig) error {
	// 调用基类初始化
	if err := s.BaseStrategy.Initialize(ctx, config); err != nil {
		return err
	}
	
	// 解析策略参数
	params := config.Parameters
	if period, ok := params["period"].(float64); ok {
		s.period = int(period)
	} else {
		s.period = 14 // 默认值
	}
	
	if overbought, ok := params["overbought"].(float64); ok {
		s.overbought = overbought
	} else {
		s.overbought = 70.0 // 默认值
	}
	
	if oversold, ok := params["oversold"].(float64); ok {
		s.oversold = oversold
	} else {
		s.oversold = 30.0 // 默认值
	}
	
	// 验证参数
	if s.period <= 1 {
		return fmt.Errorf("RSI周期必须大于1")
	}
	
	if s.overbought <= s.oversold {
		return fmt.Errorf("超买阈值必须大于超卖阈值")
	}
	
	if s.oversold < 0 || s.overbought > 100 {
		return fmt.Errorf("RSI阈值必须在0-100范围内")
	}
	
	return nil
}

// OnMarketData 处理市场数据
func (s *RSIStrategy) OnMarketData(ctx context.Context, data *strategy.MarketData) ([]*strategy.Signal, error) {
	// 更新价格数据
	s.updatePriceData(data.StockCode, data.ClosePrice)
	
	// 计算RSI
	rsi := s.calculateRSI(data.StockCode)
	if rsi == 0 {
		return nil, nil // 数据不足
	}
	
	// 生成交易信号
	signals := s.generateSignals(ctx, data, rsi)
	
	return signals, nil
}

// OnKLineData 处理K线数据
func (s *RSIStrategy) OnKLineData(ctx context.Context, kline *strategy.KLineData) ([]*strategy.Signal, error) {
	// 转换为市场数据格式
	marketData := &strategy.MarketData{
		StockCode:   kline.StockCode,
		Price:       kline.ClosePrice,
		Volume:      kline.Volume,
		Timestamp:   kline.Timestamp,
		OpenPrice:   kline.OpenPrice,
		HighPrice:   kline.HighPrice,
		LowPrice:    kline.LowPrice,
		ClosePrice:  kline.ClosePrice,
		Change:      kline.Change,
		ChangeRatio: kline.ChangeRatio,
	}
	
	return s.OnMarketData(ctx, marketData)
}

// Validate 验证策略配置
func (s *RSIStrategy) Validate(config *strategy.StrategyConfig) error {
	params := config.Parameters
	
	// 验证周期
	if period, ok := params["period"]; ok {
		if p, ok := period.(float64); !ok || p <= 1 || p > 50 {
			return fmt.Errorf("RSI周期必须是2-50之间的整数")
		}
	}
	
	// 验证超买阈值
	if overbought, ok := params["overbought"]; ok {
		if ob, ok := overbought.(float64); !ok || ob < 50 || ob > 90 {
			return fmt.Errorf("超买阈值必须是50-90之间的数值")
		}
	}
	
	// 验证超卖阈值
	if oversold, ok := params["oversold"]; ok {
		if os, ok := oversold.(float64); !ok || os < 10 || os > 50 {
			return fmt.Errorf("超卖阈值必须是10-50之间的数值")
		}
	}
	
	// 验证阈值关系
	if overbought, ok1 := params["overbought"].(float64); ok1 {
		if oversold, ok2 := params["oversold"].(float64); ok2 {
			if overbought <= oversold {
				return fmt.Errorf("超买阈值必须大于超卖阈值")
			}
		}
	}
	
	return nil
}

// updatePriceData 更新价格数据
func (s *RSIStrategy) updatePriceData(stockCode string, price float64) {
	// 初始化数据
	if _, exists := s.priceData[stockCode]; !exists {
		s.priceData[stockCode] = make([]float64, 0)
		s.rsiData[stockCode] = make([]float64, 0)
	}
	
	// 添加新价格
	s.priceData[stockCode] = append(s.priceData[stockCode], price)
	
	// 保持数据窗口大小
	maxLength := s.period * 3 // 保留更多历史数据用于计算
	if len(s.priceData[stockCode]) > maxLength {
		s.priceData[stockCode] = s.priceData[stockCode][len(s.priceData[stockCode])-maxLength:]
	}
}

// calculateRSI 计算RSI
func (s *RSIStrategy) calculateRSI(stockCode string) float64 {
	prices := s.priceData[stockCode]
	if len(prices) < s.period+1 {
		return 0 // 数据不足
	}
	
	// 计算价格变化
	changes := make([]float64, len(prices)-1)
	for i := 1; i < len(prices); i++ {
		changes[i-1] = prices[i] - prices[i-1]
	}
	
	if len(changes) < s.period {
		return 0
	}
	
	// 计算初始的平均涨幅和跌幅
	var avgGain, avgLoss float64
	for i := 0; i < s.period; i++ {
		if changes[i] > 0 {
			avgGain += changes[i]
		} else {
			avgLoss += math.Abs(changes[i])
		}
	}
	avgGain /= float64(s.period)
	avgLoss /= float64(s.period)
	
	// 使用威尔德平滑法计算后续的平均值
	for i := s.period; i < len(changes); i++ {
		change := changes[i]
		if change > 0 {
			avgGain = (avgGain*float64(s.period-1) + change) / float64(s.period)
			avgLoss = (avgLoss * float64(s.period-1)) / float64(s.period)
		} else {
			avgGain = (avgGain * float64(s.period-1)) / float64(s.period)
			avgLoss = (avgLoss*float64(s.period-1) + math.Abs(change)) / float64(s.period)
		}
	}
	
	// 计算RSI
	var rsi float64
	if avgLoss == 0 {
		rsi = 100
	} else {
		rs := avgGain / avgLoss
		rsi = 100 - (100 / (1 + rs))
	}
	
	// 保存RSI数据
	s.rsiData[stockCode] = append(s.rsiData[stockCode], rsi)
	if len(s.rsiData[stockCode]) > 100 {
		s.rsiData[stockCode] = s.rsiData[stockCode][1:]
	}
	
	return rsi
}

// generateSignals 生成交易信号
func (s *RSIStrategy) generateSignals(ctx context.Context, data *strategy.MarketData, rsi float64) []*strategy.Signal {
	var signals []*strategy.Signal
	
	// 获取历史RSI数据用于判断趋势
	rsiList := s.rsiData[data.StockCode]
	if len(rsiList) < 2 {
		return nil // 需要更多历史数据
	}
	
	// 获取前一个时刻的RSI值
	prevRSI := rsiList[len(rsiList)-2]
	
	var signalType strategy.SignalType
	var reason string
	var confidence float64
	
	// 超卖区域买入信号：RSI从超卖区域向上突破
	if prevRSI <= s.oversold && rsi > s.oversold {
		signalType = strategy.SignalBuy
		reason = fmt.Sprintf("RSI超卖反弹信号：RSI从%.2f上升至%.2f，突破超卖线%.2f", prevRSI, rsi, s.oversold)
		confidence = s.calculateConfidence(rsi, true)
	} else if prevRSI >= s.overbought && rsi < s.overbought {
		// 超买区域卖出信号：RSI从超买区域向下突破
		signalType = strategy.SignalSell
		reason = fmt.Sprintf("RSI超买回落信号：RSI从%.2f下降至%.2f，跌破超买线%.2f", prevRSI, rsi, s.overbought)
		confidence = s.calculateConfidence(rsi, false)
	} else {
		// 无信号
		return nil
	}
	
	// 检查是否重复信号
	lastSignal, exists := s.lastSignals[data.StockCode]
	if exists && lastSignal == signalType {
		return nil // 避免重复信号
	}
	
	// 创建信号
	signal := &strategy.Signal{
		StrategyID: s.GetContext().Config.ID,
		StockCode:  data.StockCode,
		SignalType: signalType,
		Price:      data.Price,
		Quantity:   s.calculateQuantity(data, rsi),
		Confidence: confidence,
		Reason:     reason,
		Timestamp:  gtime.Now(),
		ExtraData: map[string]interface{}{
			"rsi":        rsi,
			"prev_rsi":   prevRSI,
			"overbought": s.overbought,
			"oversold":   s.oversold,
			"volume":     data.Volume,
		},
	}
	
	signals = append(signals, signal)
	
	// 记录最后信号
	s.lastSignals[data.StockCode] = signalType
	
	return signals
}

// calculateConfidence 计算信号置信度
func (s *RSIStrategy) calculateConfidence(rsi float64, isBuy bool) float64 {
	// 基础置信度
	baseConfidence := 0.6
	
	var distanceBonus float64
	if isBuy {
		// 买入信号：RSI越接近超卖线下方，置信度越高
		if rsi < s.oversold {
			distance := s.oversold - rsi
			distanceBonus = math.Min(distance/20, 0.3) // 最大加成0.3
		}
	} else {
		// 卖出信号：RSI越接近超买线上方，置信度越高
		if rsi > s.overbought {
			distance := rsi - s.overbought
			distanceBonus = math.Min(distance/20, 0.3) // 最大加成0.3
		}
	}
	
	confidence := baseConfidence + distanceBonus
	
	// 限制在0-1范围内
	if confidence > 1.0 {
		confidence = 1.0
	}
	if confidence < 0.0 {
		confidence = 0.0
	}
	
	return confidence
}

// calculateQuantity 计算交易数量
func (s *RSIStrategy) calculateQuantity(data *strategy.MarketData, rsi float64) int {
	// 基础数量
	baseQuantity := 100
	
	// 根据RSI极值调整数量
	var multiplier float64 = 1.0
	
	if rsi <= 20 || rsi >= 80 {
		multiplier = 2.0 // RSI极值时加大仓位
	} else if rsi <= 25 || rsi >= 75 {
		multiplier = 1.5
	}
	
	// 根据价格调整数量
	if data.Price > 100 {
		baseQuantity = 50 // 高价股减少数量
	} else if data.Price > 50 {
		baseQuantity = 100
	} else {
		baseQuantity = 200 // 低价股增加数量
	}
	
	return int(float64(baseQuantity) * multiplier)
}

// 注册策略
func init() {
	// 注册参数配置
	configManager := strategy.GetConfigManager()
	params := []*strategy.ParameterConfig{
		{
			Name:         "period",
			Type:         strategy.ParamTypeInt,
			DefaultValue: 14,
			Required:     true,
			Description:  "RSI计算周期",
			Label:        "计算周期",
			Group:        "基础参数",
			Order:        1,
			Validator:    &strategy.IntValidator{Min: intPtr(2), Max: intPtr(50)},
		},
		{
			Name:         "overbought",
			Type:         strategy.ParamTypeFloat,
			DefaultValue: 70.0,
			Required:     true,
			Description:  "超买阈值",
			Label:        "超买线",
			Group:        "信号参数",
			Order:        2,
			Validator:    &strategy.FloatValidator{Min: floatPtr(50.0), Max: floatPtr(90.0)},
		},
		{
			Name:         "oversold",
			Type:         strategy.ParamTypeFloat,
			DefaultValue: 30.0,
			Required:     true,
			Description:  "超卖阈值",
			Label:        "超卖线",
			Group:        "信号参数",
			Order:        3,
			Validator:    &strategy.FloatValidator{Min: floatPtr(10.0), Max: floatPtr(50.0)},
		},
	}
	
	configManager.RegisterParameterSchema("rsi", params)
}

// 辅助函数
func floatPtr(f float64) *float64 {
	return &f
}